
#include <brpc/server.h>
#include <butil/logging.h>
#include <memory>

#include "es_factory.hpp" // es数据管理客户端封装
#include "es_user.hpp"

#include "mysql_chat_session_member.hpp" // mysql数据管理客户端封装
#include "mysql_chat_session.hpp"        // mysql数据管理客户端封装
#include "mysql_relation.hpp"            // mysql数据管理客户端封装
#include "mysql_apply.hpp"               // mysql数据管理客户端封装

#include "etcd.hpp"    // 服务注册模块封装
#include "logger.hpp"  // 日志模块封装
#include "utils.hpp"   // 基础工具接口
#include "channel.hpp" // 信道管理模块封装

#include "friend.pb.h"  // protobuf框架代码
#include "base.pb.h"    // protobuf框架代码
#include "user.pb.h"    // protobuf框架代码
#include "message.pb.h" // protobuf框架代码

class FriendServiceImpl : public lch_im::FriendService
{
public:
    FriendServiceImpl(const std::shared_ptr<elasticlient::Client> &es_client,
                      const std::shared_ptr<odb::core::database> &mysql_client,
                      const ServiceManager::ptr manager_channel,
                      const std::string &user_service_name,
                      const std::string &message_service_name)
        : _es_user(std::make_shared<ESUser>(es_client)),
          _mysql_apply(std::make_shared<FriendApplyTable>(mysql_client)),
          _mysql_chat_session(std::make_shared<ChatSessionTable>(mysql_client)),
          _mysql_chat_session_member(std::make_shared<ChatSessionMemberTable>(mysql_client)),
          _mysql_relation(std::make_shared<RelationTable>(mysql_client)),
          _user_service_name(user_service_name),
          _message_service_name(message_service_name),
          _manager_channels(manager_channel)
    {
    }

    virtual void GetFriendList(google::protobuf::RpcController *controller,
                               const ::lch_im::GetFriendListReq *request,
                               ::lch_im::GetFriendListRsp *response,
                               ::google::protobuf::Closure *done)
    {
        brpc::ClosureGuard rpc_guard(done);
        // 定义错误处理函数，不合法出错就调用
        auto err_response = [this, response](const std::string &rid, const std::string &errmsg) -> void
        {
            response->set_request_id(rid);
            response->set_success(false);
            response->set_errmsg(errmsg);
        };

        // 通过用户ID获取好友列表
        std::string rid = request->request_id();
        std::string uid = request->user_id();

        // 通过数据库来查找好友ID
        std::vector<std::string> friend_list_id = _mysql_relation->friends(uid);
        std::unordered_set<std::string> user_id_list;
        for (auto id : friend_list_id)
        {
            user_id_list.insert(id);
        }

        // 从用户子服务中获取用户的信息
        std::unordered_map<std::string, lch_im::UserInfo> user_list;
        bool ret = GetUserInfo(rid, user_id_list, user_list);
        if (ret == false)
        {
            LOG_ERROR("批量获取用户信息失败", rid);
            return err_response(rid, "批量获取用户信息失败");
        }

        response->set_request_id(rid);
        response->set_success(true);
        for (auto &e : user_list)
        {
            auto user_info = response->add_friend_list();
            user_info->CopyFrom(e.second);
        }
    }
    virtual void FriendRemove(google::protobuf::RpcController *controller,
                              const ::lch_im::FriendRemoveReq *request,
                              ::lch_im::FriendRemoveRsp *response,
                              ::google::protobuf::Closure *done)
    {
        brpc::ClosureGuard rpc_guard(done);
        // 定义错误处理函数，不合法出错就调用
        auto err_response = [this, response](const std::string &rid, const std::string &errmsg) -> void
        {
            response->set_request_id(rid);
            response->set_success(false);
            response->set_errmsg(errmsg);
        };

        // 获取好友的ID，确定要删除的对象
        std::string rid = request->request_id();
        std::string uid = request->user_id();
        std::string pid = request->peer_id();
        // 从数据库中删除好友
        bool ret = _mysql_relation->remove(uid, pid);
        if (ret == false)
        {
            LOG_ERROR("{} 删除好友失败", rid);
            return err_response(rid, "删除好友失败");
        }

        response->set_request_id(rid);
        response->set_success(true);
    }
    virtual void FriendAdd(::google::protobuf::RpcController *controller,
                           const ::lch_im::FriendAddReq *request,
                           ::lch_im::FriendAddRsp *response,
                           ::google::protobuf::Closure *done)
    {
        LOG_DEBUG("收到好友添加请求");
        brpc::ClosureGuard rpc_guard(done);
        // 定义错误处理函数，不合法出错就调用
        auto err_response = [this, response](const std::string &rid, const std::string &errmsg) -> void
        {
            response->set_request_id(rid);
            response->set_success(false);
            response->set_errmsg(errmsg);
        };

        // 获取要添加的好友ID
        std::string rid = request->request_id();
        std::string uid = request->user_id();
        std::string pid = request->respondent_id();
        // 从数据库中添加好友申请
        //  先判断是否已经是好友关系
        bool ret = _mysql_relation->exists(uid, pid);
        if (ret == true)
        {
            LOG_ERROR("{} 申请好友失败{}-{},已经是好友关系", rid, uid, pid);
            return err_response(rid, "两者已经是好友关系！");
        }

        // 判断是否已经发送了申请
        ret = _mysql_apply->exists(uid, pid);
        if (ret == true)
        {
            LOG_ERROR("{}- 申请好友失败-已经申请过对方好友！", rid, uid, pid);
            return err_response(rid, "已经申请过对方好友！");
        }

        std::string eid = uuid();
        FriendApply ev(eid, uid, pid);
        ret = _mysql_apply->insert(ev);
        if (ret == false)
        {
            LOG_ERROR("{} - 向数据库新增好友申请事件失败！", rid);
            return err_response(rid, "向数据库新增好友申请事件失败！");
        }

        response->set_request_id(rid);
        response->set_success(true);
        response->set_notify_event_id(eid);
        LOG_DEBUG("收到好友添加请求完成");
    }
    // 好友申请的处理
    virtual void FriendAddProcess(google::protobuf::RpcController *controller,
                                  const ::lch_im::FriendAddProcessReq *request,
                                  ::lch_im::FriendAddProcessRsp *response,
                                  ::google::protobuf::Closure *done)
    {
        brpc::ClosureGuard rpc_guard(done);
        // 定义错误处理函数，不合法出错就调用
        auto err_response = [this, response](const std::string &rid, const std::string &errmsg) -> void
        {
            response->set_request_id(rid);
            response->set_success(false);
            response->set_errmsg(errmsg);
        };

        // 获取事件ID， 申请人ID 处理结果
        std::string rid = request->request_id();
        std::string eid = request->notify_event_id();
        bool agree = request->agree();
        std::string uid = request->user_id();       // 被申请人
        std::string pid = request->apply_user_id(); // 申请人

        // 判断是否有这个申请的事件
//        std::cout << "被申请人" << uid << std::endl;
//        std::cout << "申请人" << pid <<std::endl;
        bool ret = _mysql_apply->exists(pid,uid);
        if (ret == false)
        {
            LOG_ERROR("{}- 没有找到{}-{}对应的好友申请事件！", rid, pid, uid);
            return err_response(rid, "没有找到对应的好友申请事件!");
        }
        // 如果有就处理
        ret = _mysql_apply->remove(pid,uid);
        if (ret == false)
        {
            LOG_ERROR("{}- 从数据库删除申请事件 {}-{} 失败！", rid, pid, uid);
            return err_response(rid, "从数据库删除申请事件失败!");
        }

        // 如果是同意，那么就向数据库中添加关系
        std::string cssid;
        if (agree == true)
        {
            // 向关系表中添加关系
            ret = _mysql_relation->insert(uid, pid);
            if (ret == false)
            {
                LOG_ERROR("{}- 新增好友关系信息-{}-{}！", rid, uid, pid);
                return err_response(rid, "新增好友关系信息!");
            }

            // 向会话表中添加会话信息
            cssid = uuid();
            ChatSession cs(cssid, "", ChatSessionType::SINGLE);
            ret = _mysql_chat_session->insert(cs);
            if (ret == false)
            {
                LOG_ERROR("{}- 新增单聊会话信息-{}！", rid, cssid);
                return err_response(rid, "新增单聊会话信息失败!");
            }

            // 向会话成员表中添加信息
            ChatSessionMember csm1(cssid, uid);
            ChatSessionMember csm2(cssid, pid);
            std::vector<ChatSessionMember> csm_lists = {csm1, csm2};
            ret = _mysql_chat_session_member->append_member(csm_lists);
            if (ret == false)
            {
                if (ret == false)
                {
                    LOG_ERROR("{}- 没有找到{}-{}对应的好友申请事件！", rid, pid, uid);
                    return err_response(rid, "没有找到对应的好友申请事件!");
                }
            }
        }
        response->set_request_id(rid);
        response->set_success(true);
        response->set_new_session_id(cssid);
    }
    // 好友搜索
    virtual void FriendSearch(google::protobuf::RpcController *controller,
                              const ::lch_im::FriendSearchReq *request,
                              ::lch_im::FriendSearchRsp *response,
                              ::google::protobuf::Closure *done)
    {
        brpc::ClosureGuard rpc_guard(done);
        // 定义错误处理函数，不合法出错就调用
        auto err_response = [this, response](const std::string &rid, const std::string &errmsg) -> void
        {
            response->set_request_id(rid);
            response->set_success(false);
            response->set_errmsg(errmsg);
        };

        // 获取会话id，uid search_keys
        std::string rid = request->request_id();
        std::string uid = request->user_id();
        std::string skey = request->search_key();

        // 通过好友关系表，获取到好友的ID
        auto friend_id_lists = _mysql_relation->friends(uid);
        // 3. 从ES搜索引擎进行用户信息搜索 --- 过滤掉当前的好友
        LOG_DEBUG("{} 好友搜索: {}",uid,skey);
        std::unordered_set<std::string> user_id_lists;
        friend_id_lists.push_back(uid); // 把自己也过滤掉
        auto search_res = _es_user->search(skey, friend_id_lists);
        for (auto &it : search_res)
        {
            user_id_lists.insert(it.user_id());
        }
        std::cout << "搜索完毕结果大小: " << user_id_lists.size() <<std::endl; 
        // 根据获取到的好友ID，从用户子服务中进行批量的用户信息获取
        std::unordered_map<std::string, lch_im::UserInfo> user_list;
        bool ret = GetUserInfo(rid, user_id_lists, user_list);
        if (ret == false)
        {
            LOG_ERROR("{} - 批量获取用户信息失败!", rid);
            return err_response(rid, "批量获取用户信息失败!");
        }

        response->set_request_id(rid);
        response->set_success(true);
        for (auto e : user_list)
        {
            auto user_info = response->add_user_info();
            user_info->CopyFrom(e.second);
        }
    }

    // 获取聊天会话的作用：一个用户登录成功后，能够展示自己的历史聊天信息
    virtual void GetChatSessionList(google::protobuf::RpcController *controller,
                                    const ::lch_im::GetChatSessionListReq *request,
                                    ::lch_im::GetChatSessionListRsp *response,
                                    ::google::protobuf::Closure *done)
    {
        brpc::ClosureGuard rpc_guard(done);
        // 定义错误处理函数，不合法出错就调用
        auto err_response = [this, response](const std::string &rid, const std::string &errmsg) -> void
        {
            response->set_request_id(rid);
            response->set_success(false);
            response->set_errmsg(errmsg);
        };

        // 获取聊天会话的作用：一个用户登录成功后，能够展示自己的历史聊天信息
        std::string rid = request->request_id();
        std::string uid = request->user_id();
        // 从数据库中获取到单聊的列表
        auto sf_list = _mysql_chat_session->singleChatSession(uid);
        // 获取到所有的好友ID，从好友子服务中获取到用户的信息
        std::unordered_set<std::string> users_id_list;
        for (auto e : sf_list)
        {
            users_id_list.insert(e.friend_id);
        }

        std::unordered_map<std::string, lch_im::UserInfo> user_list;
        bool ret = GetUserInfo(rid, users_id_list, user_list);
        if (ret == false)
        {
            LOG_ERROR("{} - 批量获取用户信息失败！", rid);
            return err_response(rid, "批量获取用户信息失败!");
        }

        // 从数据库中获取到群聊
        // 4. 根据所有的会话ID，从消息存储子服务获取会话最后一条消息
        auto gc_list = _mysql_chat_session->groupChatSession(uid);
        for (auto &e : sf_list)
        {
            auto chat_session_info = response->add_chat_session_info_list();
            chat_session_info->set_single_chat_friend_id(e.friend_id);
            chat_session_info->set_chat_session_id(e.chat_session_id);
            // 单聊的名称 就是好友的名称
            chat_session_info->set_chat_session_name(user_list[e.friend_id].nickname());
            chat_session_info->set_avatar(user_list[e.friend_id].avatar());
            lch_im::MessageInfo msg;
            ret = GetRecentMsg(rid, e.chat_session_id, msg);
            if (ret == false)
            {
                continue;
            }
            chat_session_info->mutable_prev_message()->CopyFrom(msg);
        }

        for (auto &e : gc_list)
        {
            auto chat_session_info = response->add_chat_session_info_list();
            chat_session_info->set_chat_session_id(e.chat_session_id);
            chat_session_info->set_chat_session_name(e.chat_session_name);
            lch_im::MessageInfo msg;
            ret = GetRecentMsg(rid, e.chat_session_id, msg);
            if (ret == false)
            {
                continue;
            }
            chat_session_info->mutable_prev_message()->CopyFrom(msg);
        }

        response->set_request_id(rid);
        response->set_success(true);
    }
    // 会话的创建
    virtual void ChatSessionCreate(google::protobuf::RpcController *controller,
                                   const ::lch_im::ChatSessionCreateReq *request,
                                   ::lch_im::ChatSessionCreateRsp *response,
                                   ::google::protobuf::Closure *done)
    {
        brpc::ClosureGuard rpc_guard(done);
        // 定义错误处理函数，不合法出错就调用
        auto err_response = [this, response](const std::string &rid, const std::string &errmsg) -> void
        {
            response->set_request_id(rid);
            response->set_success(false);
            response->set_errmsg(errmsg);
        };

        std::string rid = request->request_id();
        std::string uid = request->user_id();
        std::string cssname = request->chat_session_name();
        // 生成会话ID，向数据库添加会话信息，添加会话成员信息
        std::string cssid = uuid();
        ChatSession cs(cssid, cssname, ChatSessionType::GROUP);
        bool ret = _mysql_chat_session->insert(cs);
        if (ret == false)
        {
            LOG_ERROR("{} - 向数据库添加会话信息失败: {}", rid, cssname);
            return err_response(rid, "向数据库添加会话信息失败!");
        }
        std::vector<ChatSessionMember> member_list;
        for (int i = 0; i < request->member_id_list_size(); i++)
        {
            ChatSessionMember csm(cssid, request->member_id_list(i));
            member_list.push_back(csm);
        }
        // 获取到了成员后，将成员向成员表中插入
        ret = _mysql_chat_session_member->append_member(member_list);
        if (ret == false)
        {
            LOG_ERROR("{} - 向数据库添加会话成员信息失败: {}", rid, cssname);
            return err_response(rid, "向数据库添加会话成员信息失败!");
        }

        response->set_request_id(rid);
        response->set_success(true);
        response->mutable_chat_session_info()->set_chat_session_id(cssid);
        response->mutable_chat_session_info()->set_chat_session_name(cssname);
    }
    // 获取群聊的成员
    virtual void GetChatSessionMember(google::protobuf::RpcController *controller,
                                      const ::lch_im::GetChatSessionMemberReq *request,
                                      ::lch_im::GetChatSessionMemberRsp *response,
                                      ::google::protobuf::Closure *done)
    {
        brpc::ClosureGuard rpc_guard(done);
        // 定义错误处理函数，不合法出错就调用
        auto err_response = [this, response](const std::string &rid, const std::string &errmsg) -> void
        {
            response->set_request_id(rid);
            response->set_success(false);
            response->set_errmsg(errmsg);
        };

        // 获取到会话ID
        std::string rid = request->request_id();
        std::string uid = request->user_id();
        std::string cssid = request->chat_session_id();
        // 从数据库中获取到成员ID
        auto member_id_list = _mysql_chat_session_member->members(cssid);
        std::unordered_set<std::string> uid_list;
        for (auto &id : member_id_list)
        {
            uid_list.insert(id);
        }
        // 从用户子服务中获取到对应的用户信息
        std::unordered_map<std::string, lch_im::UserInfo> user_list;
        bool ret = GetUserInfo(rid, uid_list, user_list);
        if (ret == false)
        {
            LOG_ERROR("{} - 从用户子服务获取用户信息失败！", rid);
            return err_response(rid, "从用户子服务获取用户信息失败!");
        }

        response->set_request_id(rid);
        response->set_success(true);
        for (auto &e : user_list)
        {
            auto user_info = response->add_member_info_list();
            user_info->CopyFrom(e.second);
        }
    }
    // 获取好友申请事件还未处理的事件ID
    virtual void GetPendingFriendEventList(google::protobuf::RpcController *controller,
                                           const ::lch_im::GetPendingFriendEventListReq *request,
                                           ::lch_im::GetPendingFriendEventListRsp *response,
                                           ::google::protobuf::Closure *done)
    {
        LOG_DEBUG("收到获取好友申请列表的请求");
        brpc::ClosureGuard rpc_guard(done);
        // 定义错误处理函数，不合法出错就调用
        auto err_response = [this, response](const std::string &rid, const std::string &errmsg) -> void
        {
            response->set_request_id(rid);
            response->set_success(false);
            response->set_errmsg(errmsg);
        };

        std::string rid = request->request_id();
        std::string uid = request->user_id();
        std::string ssid = request->session_id();
        // 从数据库中获取待处理的申请事件 ---- 申请人用户ID列表
        auto res = _mysql_apply->applyUsers(uid);
        std::unordered_set<std::string> user_id_lists;
        for (auto &id : res)
        {
            user_id_lists.insert(id);
        }
        // 从用户子服务中获取到对应的用户信息
        std::unordered_map<std::string, lch_im::UserInfo> user_list;
        bool ret = GetUserInfo(rid, user_id_lists, user_list);
        if (ret == false)
        {
            LOG_ERROR("{} - 批量获取用户信息失败!", rid);
            return err_response(rid, "批量获取用户信息失败!");
        }

        response->set_request_id(rid);
        response->set_success(true);
        for (auto &e : user_list)
        {
            auto event = response->add_event();
            event->CopyFrom(e.second);
        }
    }

    ~FriendServiceImpl() {}

private:
    bool GetRecentMsg(const std::string &rid,
                      const std::string &cssid,
                      lch_im::MessageInfo &msg)

    {
        auto channel = _manager_channels->choose(_message_service_name);
        if (!channel)
        {
            LOG_ERROR("{} - 获取用户子服务信道失败！！", rid);
            return false;
        }
        lch_im::GetRecentMsgReq req;
        lch_im::GetRecentMsgRsp rsp;
        req.set_request_id(rid);
        req.set_msg_count(1);
        brpc::Controller cntl;
        lch_im::MsgStorageService_Stub stub(channel.get());
        stub.GetRecentMsg(&cntl, &req, &rsp, nullptr);
        if (cntl.Failed() == true)
        {
            LOG_ERROR("{} - 消息存储子服务调用失败: {}", rid, cntl.ErrorText());
            return false;
        }
        if (rsp.success() == false)
        {
            LOG_ERROR("{} - 获取会话 {} 最近消息失败: {}", rid, cssid, rsp.errmsg());
            return false;
        }
        if (rsp.msg_list_size() > 0)
        {
            msg.CopyFrom(rsp.msg_list(0));
            return true;
        }
        return false;
    }

    bool GetUserInfo(const std::string &rid,
                     const std::unordered_set<std::string> &uid_list,
                     std::unordered_map<std::string, lch_im::UserInfo> &user_list)
    {
        auto channel = _manager_channels->choose(_user_service_name);
        if (!channel)
        {
            LOG_ERROR("{} - 获取用户子服务信道失败！！", rid);
            return false;
        }

        lch_im::GetMultiUserInfoReq req;
        lch_im::GetMultiUserInfoRsp rsp;
        req.set_request_id(rid);
        for (auto &id : uid_list)
        {
            req.add_users_id(id);
        }

        brpc::Controller cntl;
        lch_im::UserService_Stub stub(channel.get());
        stub.GetMultiUserInfo(&cntl, &req, &rsp, nullptr);
        if (cntl.Failed() == true)
        {
            LOG_ERROR("{} - 用户子服务调用失败: {}", rid, cntl.ErrorText());
            return false;
        }

        if (rsp.success() == false)
        {
            LOG_ERROR("{} - 批量获取用户信息失败: {}", rid, rsp.errmsg());
            return false;
        }
        for (auto &e : rsp.users_info())
        {
            user_list.insert(std::make_pair(e.first, e.second));
        }

        return true;
    }

private:
    ESUser::ptr _es_user;
    FriendApplyTable::ptr _mysql_apply;
    ChatSessionTable::ptr _mysql_chat_session;
    ChatSessionMemberTable::ptr _mysql_chat_session_member;
    RelationTable::ptr _mysql_relation;
    // 这边是rpc调用客户端相关对象
    std::string _message_service_name;
    std::string _user_service_name;
    ServiceManager::ptr _manager_channels;
};

class FriendServer
{
public:
    using ptr = std::shared_ptr<FriendServer>;

    FriendServer(const Discovery::ptr &service_discoverer,
                 const std::shared_ptr<elasticlient::Client> es_client,
                 const std::shared_ptr<odb::core::database> mysql_client,
                 const Registery::ptr &reg_client,
                 const std::shared_ptr<brpc::Server> rpc_server)
        : _service_discoverer(service_discoverer),
          _es_client(es_client),
          _mysql_client(mysql_client),
          _reg_client(reg_client),
          _rpc_server(rpc_server)
    {
    }

    ~FriendServer() {}

    void start()
    {
        _rpc_server->RunUntilAskedToQuit();
    }

private:
    Discovery::ptr _service_discoverer;
    std::shared_ptr<elasticlient::Client> _es_client;
    std::shared_ptr<odb::core::database> _mysql_client;
    Registery::ptr _reg_client;
    std::shared_ptr<brpc::Server> _rpc_server;
};

class FriendServerBuild
{
public:
    // 创建es对象
    void create_es_object(const std::vector<std::string> host_list)
    {
        _es_client = ESClientFactory::create(host_list);
    }

    // 创建mysql对象
    void create_mysql_object(
        const std::string &user,
        const std::string &pswd,
        const std::string &db,
        const std::string &host,
        const std::string &cset,
        int port,
        int connect_pool_count)
    {
        _mysql_client = ODBFactory::create(user, pswd, db, host, cset, port, connect_pool_count);
    }

    void create_discovery_object(const std::string &reg_host,
                                 const std::string &base_service_name,
                                 const std::string &user_service_name,
                                 const std::string &message_service_name)
    {
        _user_service_name = user_service_name;
        _message_service_name = message_service_name;
        _manager_channels = std::make_shared<ServiceManager>();
        // 设置关心的对象
        _manager_channels->declared(_user_service_name);
        _manager_channels->declared(_message_service_name);
        LOG_DEBUG("设置用户子服务为需添加管理的子服务：{}", user_service_name);
        LOG_DEBUG("设置消息子服务为需添加管理的子服务：{}", message_service_name);
        auto pub_cb = std::bind(&ServiceManager::onServiceOnline, _manager_channels.get(), std::placeholders::_1, std::placeholders::_2);
        auto del_cb = std::bind(&ServiceManager::onServiceOffline, _manager_channels.get(), std::placeholders::_1, std::placeholders::_2);
        _service_discoverer = std::make_shared<Discovery>(reg_host, base_service_name, pub_cb, del_cb);
    }

    void create_registry_object(const std::string &reg_host, const std::string &service_name, const std::string &access_host)
    {
        _registery_client = std::make_shared<Registery>(reg_host);
        _registery_client->registry(service_name, access_host);
    }

    void create_rpc_server(uint16_t port, int32_t timeout, uint8_t num_threads, const std::string &path = "./data/")
    {
        if (!_es_client)
        {
            LOG_ERROR("还未初始化es客户端");
            abort();
        }

        if (!_mysql_client)
        {
            LOG_ERROR("还未初始化mysql客户端");
            abort();
        }

        if (!_manager_channels)
        {
            LOG_ERROR("还未初始化信道管理模块！");
            abort();
        }
        _rpc_server = std::make_shared<brpc::Server>();
        FriendServiceImpl *friend_service = new FriendServiceImpl(_es_client,
                                                                _mysql_client,
                                                                _manager_channels,
                                                                _user_service_name,
                                                                _message_service_name);
        int ret = _rpc_server->AddService(friend_service,
                                          brpc::ServiceOwnership::SERVER_OWNS_SERVICE);
        if (ret == -1)
        {
            LOG_ERROR("添加Rpc服务失败！");
            abort();
        }

        // 启动服务器
        brpc::ServerOptions options;
        // 连接空闲超时时间，-1表示
        options.idle_timeout_sec = -1;
        // io线程数量
        options.num_threads = 1;
        ret = _rpc_server->Start(port, &options);
        if (ret == -1)
        {
            LOG_ERROR("服务启动失败");
            abort();
        }
    }

    FriendServer::ptr build()
    {
        if (!_service_discoverer)
        {
            LOG_ERROR("没有初始化服务发现服务");
            abort();
        }

        if (!_registery_client)
        {
            LOG_ERROR("没有初始化服务注册服务");
            abort();
        }

        if (!_rpc_server)
        {
            LOG_ERROR("没有初始化rpc服务");
            abort();
        }

        FriendServer::ptr server = std::make_shared<FriendServer>(_service_discoverer, _es_client, _mysql_client,
                                                                  _registery_client, _rpc_server);
        return server;
    }

private:
    Registery::ptr _registery_client;

    std::shared_ptr<elasticlient::Client> _es_client;
    std::shared_ptr<odb::core::database> _mysql_client;

    std::string _user_service_name;
    std::string _message_service_name;

    ServiceManager::ptr _manager_channels;
    Discovery::ptr _service_discoverer;

    std::shared_ptr<brpc::Server> _rpc_server;
};
